﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Cinch;
using System.ComponentModel;
using System.ComponentModel.Composition;

namespace Anata.Client
{
    /// <summary>
    /// Represents a single Image ViewModel
    /// </summary>
    public class PromoViewModel : EditableValidatingViewModelBase
    {
        #region Data

        private ViewMode currentViewMode = ViewMode.AddMode;

        #region Data.Primitives
        private DataWrapper<Int32> idPromo;
        private DataWrapper<Int32?> idLayanan;
        private String namaLayanan;
        private DataWrapper<Int32?> idCabang;
        private String namaCabang;
        private DataWrapper<String> nama;
        private DataWrapper<Boolean> isPersentase;
        private DataWrapper<Double> persentasePromo;
        private DataWrapper<Int32> nominalPromo;
        private DataWrapper<String> syarat;
        private DataWrapper<Boolean> isOnce;
        private DataWrapper<Boolean> isDaily;
        private DataWrapper<Boolean> isWeekly;
        private DataWrapper<Boolean> isMonthly;
        private DataWrapper<Boolean> isYearly;
        private DataWrapper<DateTime?> waktuMulai;
        private DataWrapper<DateTime?> waktuSelesai;

        private bool isBusy = false;
        #endregion

        private IEnumerable<DataWrapperBase> cachedListOfDataWrappers;

        #region Data.Rules
        #endregion

        #region Data.VMs
        #endregion

        #region Data.Services
        private IMessageBoxService messageBoxService;
        private IUIVisualizerService uiVisualizerService;
        private IReferenceProvider referenceProvider;
        #endregion

        #endregion

        #region Constructor
        [ImportingConstructor]
        public PromoViewModel(
            IMessageBoxService messageBoxService,
            IUIVisualizerService uiVisualizerService,
            IReferenceProvider referenceProvider)
        {
            #region Constructor.SetupServices
            this.messageBoxService = messageBoxService;
            this.uiVisualizerService = uiVisualizerService;
            this.referenceProvider = referenceProvider;
            #endregion

            #region Constructor.SetupCommands
            CabangSelectCommand = new SimpleCommand<Object, Object>(CanExecuteCabangSelectCommand, ExecuteCabangSelectCommand);
            LayananSelectCommand = new SimpleCommand<Object, Object>(CanExecuteLayananSelectCommand, ExecuteLayananSelectCommand);
            PromoDeleteCommand = new SimpleCommand<Object, Object>(CanExecutePromoDeleteCommand, ExecutePromoDeleteCommand);
            #endregion

            #region Constructor.CreateDataWrappers
            IdPromo = new DataWrapper<Int32>(this, idPromoChangeArgs);
            IdPromo.IsEditable = true;
            IdLayanan = new DataWrapper<Int32?>(this, idLayananChangeArgs);
            IdLayanan.IsEditable = true;
            IdCabang = new DataWrapper<Int32?>(this, idCabangChangeArgs);
            IdCabang.IsEditable = true;
            Nama = new DataWrapper<String>(this, namaChangeArgs);
            Nama.IsEditable = true;
            IsPersentase = new DataWrapper<Boolean>(this, isPersentaseChangeArgs);
            IsPersentase.IsEditable = true;
            PersentasePromo = new DataWrapper<Double>(this, persentasePromoChangeArgs);
            PersentasePromo.IsEditable = true;
            NominalPromo = new DataWrapper<Int32>(this, nominalPromoChangeArgs);
            NominalPromo.IsEditable = true;
            Syarat = new DataWrapper<String>(this, syaratChangeArgs);
            Syarat.IsEditable = true;
            IsOnce = new DataWrapper<Boolean>(this, isOnceChangeArgs);
            IsOnce.IsEditable = true;
            IsDaily = new DataWrapper<Boolean>(this, isDailyChangeArgs);
            IsDaily.IsEditable = true;
            IsWeekly = new DataWrapper<Boolean>(this, isWeeklyChangeArgs);
            IsWeekly.IsEditable = true;
            IsMonthly = new DataWrapper<Boolean>(this, isMonthlyChangeArgs);
            IsMonthly.IsEditable = true;
            IsYearly = new DataWrapper<Boolean>(this, isYearlyChangeArgs);
            IsYearly.IsEditable = true;
            WaktuMulai = new DataWrapper<DateTime?>(this, waktuMulaiChangeArgs);
            WaktuMulai.IsEditable = true;
            WaktuSelesai = new DataWrapper<DateTime?>(this, waktuSelesaiChangeArgs);
            WaktuSelesai.IsEditable = true;
            #endregion

            //fetch list of all DataWrappers, so they can be used again later without the
            //need for reflection
            cachedListOfDataWrappers =
                DataWrapperHelper.GetWrapperProperties<PromoViewModel>(this);

            #region Create Validation Rules
            #endregion

            #region Constructor.SetupCollections
            #endregion
        }
        #endregion

        #region Static
        static PromoViewModel()
        {
        }
        #endregion

        #region Public Properties

        #region Public.Commands
        public SimpleCommand<Object, Object> CabangSelectCommand { get; private set; }
        public SimpleCommand<Object, Object> LayananSelectCommand { get; private set; }
        public SimpleCommand<Object, Object> PromoDeleteCommand { get; private set; }
        #endregion

        #region Public.ViewMode
        /// <summary>
        /// The current ViewMode, when changed will loop
        /// through all nested DataWrapper objects and change
        /// their state also
        /// </summary>

        static PropertyChangedEventArgs currentViewModeChangeArgs =
            ObservableHelper.CreateArgs<PromoViewModel>(x => x.CurrentViewMode);

        public ViewMode CurrentViewMode
        {
            get { return currentViewMode; }
            set
            {
                currentViewMode = value;

                switch (currentViewMode)
                {
                    case ViewMode.AddMode:
                        //Quantity.DataValue= 0;
                        this.DisplayName = "Transaksi Baru";
                        break;
                    case ViewMode.EditMode:
                        this.DisplayName = "Ubah Transaksi";
                        break;
                    case ViewMode.ViewOnlyMode:
                        this.DisplayName = "Lihat Transaksi";
                        break;
                }

                //Now change all the CachedListOfDataWrappers
                //Which sets all the Cinch.DataWrapper<T>s to the correct IsEditable
                //state based on the new ViewMode applied to the ViewModel
                //we can use the Cinch.DataWrapperHelper class for this
                DataWrapperHelper.SetMode(
                    CachedListOfDataWrappers,
                    currentViewMode);

                NotifyPropertyChanged(currentViewModeChangeArgs);
            }
        }
        #endregion

        #region Public.Data
        /// <summary>
        /// </summary>
        static PropertyChangedEventArgs idPromoChangeArgs =
            ObservableHelper.CreateArgs<PromoViewModel>(x => x.IdPromo);
        public DataWrapper<Int32> IdPromo
        {
            get { return idPromo; }
            set
            {
                idPromo = value;
                NotifyPropertyChanged(idPromoChangeArgs);
            }
        }
        /// <summary>
        /// </summary>
        static PropertyChangedEventArgs idLayananChangeArgs =
            ObservableHelper.CreateArgs<PromoViewModel>(x => x.IdLayanan);
        public DataWrapper<Int32?> IdLayanan
        {
            get { return idLayanan; }
            set
            {
                idLayanan = value;
                NotifyPropertyChanged(idLayananChangeArgs);
            }
        }
        /// <summary>
        /// </summary>
        static PropertyChangedEventArgs namaLayananChangeArgs =
            ObservableHelper.CreateArgs<PromoViewModel>(x => x.NamaLayanan);
        public String NamaLayanan
        {
            get { return namaLayanan; }
            set
            {
                namaLayanan = value;
                NotifyPropertyChanged(namaLayananChangeArgs);
            }
        }
        /// <summary>
        /// </summary>
        static PropertyChangedEventArgs idCabangChangeArgs =
            ObservableHelper.CreateArgs<PromoViewModel>(x => x.IdCabang);
        public DataWrapper<Int32?> IdCabang
        {
            get { return idCabang; }
            set
            {
                idCabang = value;
                NotifyPropertyChanged(idCabangChangeArgs);
            }
        }
        /// <summary>
        /// </summary>
        static PropertyChangedEventArgs namaCabangChangeArgs =
            ObservableHelper.CreateArgs<PromoViewModel>(x => x.NamaCabang);
        public String NamaCabang
        {
            get { return namaCabang; }
            set
            {
                namaCabang = value;
                NotifyPropertyChanged(namaCabangChangeArgs);
            }
        }
        /// <summary>
        /// </summary>
        static PropertyChangedEventArgs namaChangeArgs =
            ObservableHelper.CreateArgs<PromoViewModel>(x => x.Nama);
        public DataWrapper<String> Nama
        {
            get { return nama; }
            set
            {
                nama = value;
                NotifyPropertyChanged(namaChangeArgs);
            }
        }
        /// <summary>
        /// </summary>
        static PropertyChangedEventArgs isPersentaseChangeArgs =
            ObservableHelper.CreateArgs<PromoViewModel>(x => x.IsPersentase);
        public DataWrapper<Boolean> IsPersentase
        {
            get { return isPersentase; }
            set
            {
                isPersentase = value;
                NotifyPropertyChanged(isPersentaseChangeArgs);
            }
        }
        /// <summary>
        /// </summary>
        static PropertyChangedEventArgs persentasePromoChangeArgs =
            ObservableHelper.CreateArgs<PromoViewModel>(x => x.PersentasePromo);
        public DataWrapper<Double> PersentasePromo
        {
            get { return persentasePromo; }
            set
            {
                persentasePromo = value;
                NotifyPropertyChanged(persentasePromoChangeArgs);
            }
        }
        /// <summary>
        /// </summary>
        static PropertyChangedEventArgs nominalPromoChangeArgs =
            ObservableHelper.CreateArgs<PromoViewModel>(x => x.NominalPromo);
        public DataWrapper<Int32> NominalPromo
        {
            get { return nominalPromo; }
            set
            {
                nominalPromo = value;
                NotifyPropertyChanged(nominalPromoChangeArgs);
            }
        }
        /// <summary>
        /// </summary>
        static PropertyChangedEventArgs syaratChangeArgs =
            ObservableHelper.CreateArgs<PromoViewModel>(x => x.Syarat);
        public DataWrapper<String> Syarat
        {
            get { return syarat; }
            set
            {
                syarat = value;
                NotifyPropertyChanged(syaratChangeArgs);
            }
        }
        /// <summary>
        /// </summary>
        static PropertyChangedEventArgs isOnceChangeArgs =
            ObservableHelper.CreateArgs<PromoViewModel>(x => x.IsOnce);
        public DataWrapper<Boolean> IsOnce
        {
            get { return isOnce; }
            set
            {
                isOnce = value;
                NotifyPropertyChanged(isOnceChangeArgs);
            }
        }
        /// <summary>
        /// </summary>
        static PropertyChangedEventArgs isDailyChangeArgs =
            ObservableHelper.CreateArgs<PromoViewModel>(x => x.IsDaily);
        public DataWrapper<Boolean> IsDaily
        {
            get { return isDaily; }
            set
            {
                isDaily = value;
                NotifyPropertyChanged(isDailyChangeArgs);
            }
        }
        /// <summary>
        /// </summary>
        static PropertyChangedEventArgs isWeeklyChangeArgs =
            ObservableHelper.CreateArgs<PromoViewModel>(x => x.IsWeekly);
        public DataWrapper<Boolean> IsWeekly
        {
            get { return isWeekly; }
            set
            {
                isWeekly = value;
                NotifyPropertyChanged(isWeeklyChangeArgs);
            }
        }
        /// <summary>
        /// </summary>
        static PropertyChangedEventArgs isMonthlyChangeArgs =
            ObservableHelper.CreateArgs<PromoViewModel>(x => x.IsMonthly);
        public DataWrapper<Boolean> IsMonthly
        {
            get { return isMonthly; }
            set
            {
                isMonthly = value;
                NotifyPropertyChanged(isMonthlyChangeArgs);
            }
        }
        /// <summary>
        /// </summary>
        static PropertyChangedEventArgs isYearlyChangeArgs =
            ObservableHelper.CreateArgs<PromoViewModel>(x => x.IsYearly);
        public DataWrapper<Boolean> IsYearly
        {
            get { return isYearly; }
            set
            {
                isYearly = value;
                NotifyPropertyChanged(isYearlyChangeArgs);
            }
        }
        /// <summary>
        /// </summary>
        static PropertyChangedEventArgs waktuMulaiChangeArgs =
            ObservableHelper.CreateArgs<PromoViewModel>(x => x.WaktuMulai);
        public DataWrapper<DateTime?> WaktuMulai
        {
            get { return waktuMulai; }
            set
            {
                waktuMulai = value;
                NotifyPropertyChanged(waktuMulaiChangeArgs);
            }
        }
        /// <summary>
        /// </summary>
        static PropertyChangedEventArgs waktuSelesaiChangeArgs =
            ObservableHelper.CreateArgs<PromoViewModel>(x => x.WaktuSelesai);
        public DataWrapper<DateTime?> WaktuSelesai
        {
            get { return waktuSelesai; }
            set
            {
                waktuSelesai = value;
                NotifyPropertyChanged(waktuSelesaiChangeArgs);
            }
        }
        #endregion

        #region Public.IsBusy
        /// <summary>
        /// </summary>
        static PropertyChangedEventArgs isBusyChangeArgs =
            ObservableHelper.CreateArgs<PromoViewModel>(x => x.IsBusy);
        public bool IsBusy
        {
            get { return isBusy; }
            set
            {
                isBusy = value;
                NotifyPropertyChanged(isBusyChangeArgs);
            }
        }
        #endregion

        #region Public.Cached Collection
        /// <summary>
        /// Returns cached collection of DataWrapperBase
        /// </summary>
        public IEnumerable<DataWrapperBase> CachedListOfDataWrappers
        {
            get { return cachedListOfDataWrappers; }
        }
        #endregion

        #region Public.DataVM
        #endregion

        #region Public.SummaryData
        #endregion

        #endregion

        #region Command Handlers
        /// <summary>
        /// </summary>
        private bool CanExecuteCabangSelectCommand(Object args)
        {
            return !isBusy && CurrentViewMode != ViewMode.ViewOnlyMode;
        }
        /// <summary>
        /// </summary>
        private void ExecuteCabangSelectCommand(Object args)
        {
            CabangSelectViewModel csvm = new CabangSelectViewModel(
                messageBoxService,
                uiVisualizerService,
                referenceProvider);
            bool? result = uiVisualizerService.ShowDialog("CabangSelectPopup", csvm);
            if (result.HasValue && result.Value)
            {
                CabangThumbnailViewModel ctvm = (CabangThumbnailViewModel)
                    csvm.CabangsCV.CurrentItem;
                this.IdCabang.DataValue = ctvm.IdCabang;
                this.NamaCabang = ctvm.Nama;
            }
        }

        /// <summary>
        /// </summary>
        private bool CanExecuteLayananSelectCommand(Object args)
        {
            return !isBusy && CurrentViewMode != ViewMode.ViewOnlyMode;
        }
        /// <summary>
        /// </summary>
        private void ExecuteLayananSelectCommand(Object args)
        {
            LayananSelectViewModel lsvm = new LayananSelectViewModel(
                messageBoxService,
                uiVisualizerService,
                referenceProvider);
            bool? result = uiVisualizerService.ShowDialog("LayananSelectPopup", lsvm);
            if (result.HasValue && result.Value)
            {
                LayananThumbnailViewModel ltvm = (LayananThumbnailViewModel)
                    lsvm.LayanansCV.CurrentItem;
                this.IdLayanan.DataValue = ltvm.IdLayanan;
                this.NamaLayanan = ltvm.Nama;
            }
        }

        /// <summary>
        /// </summary>
        private bool CanExecutePromoDeleteCommand(Object args)
        {
            return !isBusy && CurrentViewMode != ViewMode.ViewOnlyMode;
        }
        /// <summary>
        /// </summary>
        private void ExecutePromoDeleteCommand(Object args)
        {
            Mediator.Instance.NotifyColleagues("TryRemovePromo", this);
        }
        #endregion

        #region Change Callbacks
        #endregion

        #region Private Methods
        #endregion

        #region Overrides
        static PropertyChangedEventArgs isValidChangeArgs =
            ObservableHelper.CreateArgs<PromoViewModel>(x => x.IsValid);
        public override bool IsValid
        {
            get
            {
                //return base.IsValid and use DataWrapperHelper, if you are
                //using DataWrappers
                return base.IsValid &&
                    DataWrapperHelper.AllValid(cachedListOfDataWrappers);
            }

        }
        public bool IsDirty
        {
            get
            {
                return DataWrapperHelper2.SomeDirty(cachedListOfDataWrappers);
            }
        }
        public override string ToString()
        {
            return String.Format("PromoViewModel {0}", this.idPromo);
        }
        #endregion

        #region EditableValidatingViewModelBase overrides
        protected override void OnBeginEdit()
        {
            base.OnBeginEdit();
            //Now walk the list of properties in the OrderViewModel
            //and call BeginEdit() on all Cinch.DataWrapper<T>s.
            //we can use the Cinch.DataWrapperHelper class for this
            DataWrapperHelper.SetBeginEdit(cachedListOfDataWrappers);
        }

        /// <summary>
        /// Override hook which allows us to also put any child 
        /// EditableValidatingViewModelBase objects into the EndEdit state
        /// </summary>
        protected override void OnEndEdit()
        {
            base.OnEndEdit();
            //Now walk the list of properties in the OrderViewModel
            //and call CancelEdit() on all Cinch.DataWrapper<T>s.
            //we can use the Cinch.DataWrapperHelper class for this
            DataWrapperHelper.SetEndEdit(cachedListOfDataWrappers);
        }

        /// <summary>
        /// Override hook which allows us to also put any child 
        /// EditableValidatingViewModelBase objects into the CancelEdit state
        /// </summary>
        protected override void OnCancelEdit()
        {
            base.OnCancelEdit();
            //Now walk the list of properties in the OrderViewModel
            //and call CancelEdit() on all Cinch.DataWrapper<T>s.
            //we can use the Cinch.DataWrapperHelper class for this
            DataWrapperHelper.SetCancelEdit(cachedListOfDataWrappers);
        }
        #endregion
    }
}
